using System.Collections.Generic;
using LockCrypt.Core;

namespace LockCrypt.DAL {
    public interface IDbProvider {
        /// <summary>
        /// Gets or sets the name of the filename of the database.
        /// </summary>
        /// <value>The filename of the database.</value>
        string FileName { get; set; }

        /// <summary>
        /// Gets the encryption provider.
        /// </summary>
        /// <value>The encryption provider.</value>
        IEncryptionService Encryption { get; }

        /// <summary>
        /// Gets the type of database which this provider can access.
        /// </summary>
        /// <value>The type of database which this provider can access.</value>
        Constants.DatabaseType DatabaseType { get; }

        /// <summary>
        /// Gets a value indicating whether this instance is either connected or can connect.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is connected or can connect, otherwise <c>false</c>.
        /// </value>
        bool IsConnected { get; }

        /// <summary>
        /// Checks the password entered is valid.
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if the current password is valid, otherwise <c>false</c>.
        /// </returns>
        bool CheckPassword();

        /// <summary>
        /// Changes the encryption password.
        /// </summary>
        /// <param name="newPassword">The new password.</param>
        void ChangePassword(string newPassword);

        /// <summary>
        /// Gets all items with a specified parent.
        /// </summary>
        /// <param name="parentId">The parent ID.</param>
        /// <returns></returns>
        KeyValuePair<IEnumerable<IGroup>, IEnumerable<IAccount>> GetItemsByParent(string parentId);

        #region Accounts
        /// <summary>
        /// Adds accounts to the default database.
        /// </summary>
        /// <param name="accounts">The accounts to add.</param>
        /// <param name="logger">The delegate to use to log progress (can be null).</param>
        void AddAccounts(IEnumerable<IAccount> accounts, ILogProvider logger);

        /// <summary>
        /// Edits an account.
        /// </summary>
        /// <param name="account">The account.</param>
        void EditAccount(IAccount account);

        /// <summary>
        /// Deletes an account.
        /// </summary>
        /// <param name="accountId">The account ID.</param>
        void DeleteAccount(string accountId);

        /// <summary>
        /// Gets a list of recipes from the current database file.
        /// </summary>
        /// <returns>A list of recipes in the database.</returns>
        List<IAccount> GetAccounts();

        /// <summary>
        /// Gets an account by ID.
        /// </summary>
        /// <param name="accountId">The account ID.</param>
        /// <returns>The account with the matching ID, or <c>null</c></returns>
        IAccount GetAccountByID(string accountId);
        #endregion

        #region Groups
        /// <summary>
        /// Adds account groups to the default database.
        /// </summary>
        /// <param name="groups">The groups to add.</param>
        /// <param name="logger">The delegate to use to log progress (can be null).</param>
        void AddGroups(IEnumerable<IGroup> groups, ILogProvider logger);

        /// <summary>
        /// Edits a group.
        /// </summary>
        /// <param name="group">The group.</param>
        void EditGroup(IGroup group);

        /// <summary>
        /// Deletes a group and all child groups/accounts.
        /// </summary>
        /// <param name="group">The group.</param>
        void DeleteGroup(IGroup group);

        /// <summary>
        /// Gets a list of account groups from the current database.
        /// </summary>
        /// <returns>A list of account groups in the database.</returns>
        List<IGroup> GetGroups();

        IGroup GetGroupByID(string groupId);
        #endregion

        #region Templates
        /// <summary>
        /// Adds templates to the default database.
        /// </summary>
        /// <param name="templates">The templates to add.</param>
        /// <param name="logger">The delegate to use to log progress (can be null).</param>
        /// <returns><c>null</c> on success, a log of errors on failure.</returns>
        void AddTemplates(IEnumerable<ITemplate> templates, ILogProvider logger);

        /// <summary>
        /// Edits a template.
        /// </summary>
        /// <param name="template">The template.</param>
        void EditTemplate(ITemplate template);

        /// <summary>
        /// Deletes a template.
        /// </summary>
        /// <param name="templateId">The template ID.</param>
        void DeleteTemplate(string templateId);

        /// <summary>
        /// Gets a list of templates from the current database file.
        /// </summary>
        /// <returns>A list of templates in the database.</returns>
        List<ITemplate> GetTemplates();

        /// <summary>
        /// Gets matching templates by name.
        /// </summary>
        /// <param name="templateName">Name of the template.</param>
        /// <returns>All templates with a matching name.</returns>
        List<ITemplate> GetTemplatesByName(string templateName);

        /// <summary>
        /// Gets a template by ID.
        /// </summary>
        /// <param name="templateId">The template ID.</param>
        /// <returns>The template with the matching ID, or <c>null</c></returns>
        ITemplate GetTemplateByID(string templateId);
        #endregion

        #region Database Maintenance
        /// <summary>
        /// Creates a database and required tables.
        /// </summary>
        /// <exception cref="System.Exception">Multiple exceptions, check the reference for DirectoryInfo.Create and the FileInfo constructor.</exception>
        void CreateDatabase();

        /// <summary>
        /// Clears the database.
        /// </summary>
        void ClearDatabase();

        /// <summary>
        /// Reads the whole contents of the database.
        /// </summary>
        /// <returns>The whole contents of the database.</returns>
        DatabaseContents ReadDatabase();
        #endregion
        
    }
}